from fastapi import status, UploadFile, File, Form, Query, Body
from mistralai import EmbeddingRequest
# 在文件顶部添加必要的导入
from typing import List
from .base_router import BaseRouter
from ..services.knowledge_file_service import KnowledgeFileService
from ..schemas.common import ApiResponse
from ..utils.minio_client import MinioClient
from ..utils.file_handler import UploadFile as FileUploader
from ..config import settings
from ..excepetions.base_api_exception import (
    DatabaseException,
    ValidationException,
    UnsupportedFileTypeException
)
import logging

logger = logging.getLogger(__name__)
knowledge_file_service = KnowledgeFileService()

# 配置
KB_BUCKET_NAME = settings.KB_BUCKET_NAME
# 支持的文件类型
SUPPORTED_EXTENSIONS = {
    'pdf': 'application/pdf',
    'doc': 'application/msword',
    'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    'xls': 'application/vnd.ms-excel',
    'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    'txt': 'text/plain',
    'sql': 'text/sql',
    'json': 'application/json',
    'md': 'text/markdown'
}


class FileHandleRouter(BaseRouter):
    def __init__(self):
        logger.info("Initializing FileHandleRouter")
        super().__init__()
        self.router = self._register_routes()

    # 修正路由注册方法
    import logging

    def _register_routes(self):
        """注册所有路由处理方法并添加Swagger文档注解"""
        logger = logging.getLogger(__name__)

        # 上传知识文件
        self.router.post(
            "/uploadFile",
            response_model=ApiResponse,
            status_code=status.HTTP_201_CREATED,
            summary="上传知识文件",
            description="上传文档文件（如PDF、TXT等）到系统，用于后续解析和处理",
            tags=["知识管理"]
        )(self.upload_knowledge_file)
        logger.info("Registered route: POST /uploadFile")

        self.router.get(
            "/getBucketFiles",
            response_model=ApiResponse,
            status_code=status.HTTP_200_OK,
            summary="获取存储桶内的全部文件",
            description="获取存储桶内的全部文件",
            tags=["知识管理"]
        )(self.get_bucket_files)
        logger.info("Registered route: GET /getBucketFiles")

        self.router.delete(
            "/deleteFile",
            response_model=ApiResponse,
            status_code=status.HTTP_200_OK,
            summary="删除知识文件",
            description="删除知识文件",
            tags=["知识管理"]
        )(self.delete_knowledge_file)
        logger.info("Registered route: DELETE /deleteFile")

        self.router.post(
            "/add",
            response_model=ApiResponse,
            status_code=status.HTTP_200_OK,
            summary="添加向量",
            description="添加向量",
            tags=["知识管理"]
        )(self.add_embedding)
        logger.info("Registered route: POST /add_vector")

        logger.info("All routes registered successfully")
        return self.router

    async def upload_knowledge_file(
            self,
            # 1. 所有参数显式标记，文件用 File，普通字段用 Form
            file: UploadFile = File(..., description="待上传的知识文件（支持 pdf/docx/txt/xlsx）"),
            collection_name: str = Form(..., description="知识文件所属的集合名称（必填）"),
            bucket_name: str = Form(..., description="知识文件所属的存储桶名称（必填）")
    ):
        """上传知识文件并创建记录"""
        try:
            if not file:
                raise ValidationException("No file provided")

            # 获取文件后缀并验证
            file_extension = file.filename.split('.')[-1].lower() if file.filename else ''
            if file_extension not in SUPPORTED_EXTENSIONS:
                raise UnsupportedFileTypeException(f"Unsupported file type: {file_extension}")

            # 上传文件到存储
            uploaded_file = FileUploader()
            logger.info(f"KB_BUCKET_NAME:{KB_BUCKET_NAME}")
            uploaded_object = await uploaded_file.upload_file_form(file,
                                                                   bucket_name
                                                                   )  # 假设upload_file方法已适配FastAPI的UploadFile

            if not uploaded_object:
                raise DatabaseException("Failed to upload file")

            # 创建数据库记录
            knowledge_file_param = {
                "collection_name": collection_name,
                "file_name": uploaded_object.get('stored_filename'),
                "file_type": file_extension,
                "minio_path": uploaded_object.get('file_url'),
                "chunk_strategy": 'adaptive',
                "status": 'uploaded'
            }

            knowledge_file = knowledge_file_service.save_knowledge_file(knowledge_file_param)
            logger.info(f"Uploaded knowledge file: {knowledge_file.id}")

            return ApiResponse(
                status=200,
                message="File uploaded successfully",
                data=knowledge_file.to_dict()
            )
        except ValidationException as e:
            raise
        except UnsupportedFileTypeException as e:
            raise
        except Exception as e:
            logger.error(f"Error uploading knowledge file: {str(e)}", exc_info=True)
            raise DatabaseException("Failed to upload knowledge file") from e

    # 获取桶内的全部文件
    async def get_bucket_files(self, bucket_name: str = Query(..., description="存储桶名称")):
        """获取存储桶内的全部文件"""
        try:
            minio_client = MinioClient()  # 创建实例
            minio_files = minio_client.get_bucket_objects(bucket_name)  # 通过实例调用
            return ApiResponse(
                status=200,
                message="Files retrieved successfully",
                data=minio_files
            )
        except Exception as e:
            logger.error(f"Error retrieving files from bucket: {str(e)}", exc_info=True)
            raise DatabaseException("Failed to retrieve files from bucket") from e
    # 获取数据库内的所有minio记录
    async def get_bucket_files_from_db(self):
        """获取数据库内的所有minio记录"""
        try:
            minio_files = knowledge_file_service.get_all_knowledge_files()
            return ApiResponse(
                status=200,
                message="Files retrieved successfully",
                data=minio_files
            )
        except Exception as e:
            logger.error(f"Error retrieving files from database: {str(e)}", exc_info=True)
            raise DatabaseException("Failed to retrieve files from database") from e

    # 删除数据库内对应的文件记录
    async def delete_knowledge_file(
            self,
            bucket_name: str = Query(..., description="存储桶名称"),
            object_name: str = Query(..., description="对象名称"),
            file_id: str = Query(..., description="文件ID")
    ):
        """删除知识文件"""
        try:
            file_uploader = FileUploader()
            # 根据file_id来查找对应的文件进行数据库的逻辑删除和minio的物理删除
            file_uploader.delete_file(bucket_name, object_name)
            knowledge_file_service.delete_knowledge_file(file_id)
            return ApiResponse(
                status=200,
                message="File deleted successfully",
            )
        except Exception as e:
            logger.error(f"Error deleting knowledge file: {str(e)}", exc_info=True)
            raise DatabaseException("Failed to delete knowledge file") from e
    # 路由层只需传递embedding向量
    async def add_embedding(self,
        embedding_data: List[List[float]] = Body(..., description="嵌入向量列表")
    ):
        '''添加向量入库'''
        try:
            service = KnowledgeFileService()
            # 为每条向量数据调用服务方法（因为Milvus会自动生成ID）
            results = []
            for embedding in embedding_data:
                result = service.add_embedding_to_milvus(embedding)
                results.append(result)
            return ApiResponse(
                status=200,
                message="Vectors added successfully",
                data={"success_count": len(results)}
            )
        except Exception as e:
            logger.error(f"Error adding embedding: {str(e)}", exc_info=True)
            raise DatabaseException("Failed to add embedding") from e

